#!/usr/bin/env python
# @file object.py


import os
import re
import stat

class IdentifierError(Exception):
    pass

class ReadonlyError(Exception):
    pass

class Object(dict):
    '''Object is the root of the Varix class hierarchy: all Varix
    types subclass it.'''

    _VALID_IDENTIFIER = re.compile('[A-Za-z_]\w*')

    def __init__(self, value='', items={}):
        '''Items must be set first as setting the value is understood to
        mark the variable as initialized.'''
        self.value = None

        self.update(items)
        self.value = value

    def __repr__(self):
        '''Return a constructor that could make an object like this
        one.'''
        if self:
            items = ', items=%s' % self.__items()
        else:
            items = ''

        return '%s(value=%s%s)' % (self.__class__.__name__,
                                   repr(self.value),
                                   items)

    def __setitem__(self, key, value):
        '''Set a property of the object. The association between
        variable names and values is maintained here, therefore we
        must check for valid identifiers here, and must check for
        overwriting Readonlys here.'''
        if not self._VALID_IDENTIFIER.match(key):
            raise IdentifierError, key

        if key in self and isinstance(self[key], Readonly):
            raise ReadonlyError

        dict.__setitem__(self, key, value)

    def __delitem__(self, key):
        '''Do not allow deleting readonly variables.'''
        if isinstance(self[key], Readonly):
            raise ReadonlyError

    def __str__(self):
        '''Print out the value of this object.'''
        return str(self.value)

    def __items(self):
        return dict.__repr__(self)

    def evaluate(self):
        return self.value

class Readonly(Object):
    def __init__(self, value, items={}):
        '''A Readonly is required to be passed a value on
        initialization. (what use is an uninitialized Readonly?)'''
        if not value:
            raise ValueError
        Object.__init__(self, value, items)

class List(Object):
    def __init__(self, value=[], items={}):
        Object.__init__(self, value, items)

    def __str__(self):
        s = ['[']
        if self.value:
            s += [str(self.value[0])]
        for i in self.value[1:]:
            s += [', ', str(i)]
        s += [']']
        return ''.join(s)

    def getitem(self, index):
        return self.value[index]

    def setitem(self, index, value):
        self.value[index] = value

def FileFactory(context, path):
    stat_buf = os.lstat(path)

    if stat.ST_ISDIR(stat_buf.mode):
        return Directory(context=context)

class File(Object):
    def __init__(self, context, fd):
        Object.__init__(self, context=context)

    def activate(self):
        raise NotImplementedError

class Directory(File):
    def activate(self):
        self.chdir()

    def chdir(self):
        oldpwd = os.getcwdu()

        try:
            os.chdir(directory)
            context.symbols['env']['PWD'] = Directory(os.getcwdu())
        except OSError, e:
            print e

        if context.watch():
            context.watch()[oldpwd].update(os.getcwdu())
            context.update_dents()
